﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ClassLibrary1
{
    //接口
    /**
            接口在任何一门面向对象语言里都是一个很重要的概念。总所周知面向对象语言的三大特征： 封装、继承、多态 。
            其中的多态就是靠着接口来实现的。可以说接口就是面向对象语言的精华所在。
    **/



    /** 1、接口的声明
                接口声明使用Interface关键字，定义接口的方法和定义类相似。 
                声明了接口，就是声明了一个类型，接口和类都是类型。
    **/
    interface IHowl  
    {
        void howl();//注意： 接口的方法前，不能加public、private、 Protected等访问修饰符。C#默认接口的所有方法都是public，不能更改
    }

    //声明Dog类，实现IHowl接口。
    //一个类实现某个接口就是要实现接口中定义的所有方法。
    class Dog:IHowl   //Dog类实现IHowl接口
    {
        public void howl()
        {
            string aa = "汪汪";
        }
    }

    /**
        2、如何使用接口？
    **/
    public class test
    {
       
        public static void UseIHowl()
        {
            IHowl Animal = new Dog();//定义了IHowl类型的变量Animal，却确实赋值给它Dog类型的变量？编译器没有报错，代码正常运行？
            Animal.howl();

            //这就是接口的用法。声明一个接口变量，然后赋值给它一个实现了该接口的类的实例对象，然后通过接口变量就可以调用接口中类的实例对象。
        }
    }
    //那就有了个疑问了，我直接声明一个Dog类型的变量，然后直接调用Dog的howl()方法，不是也行吗？为什么要绕个大圈去定义接口变量来调用呢？

    //现在又声明了一个Cat类，也实现了IHowl接口，但是howl()方法的内容不同
    class Cat : IHowl
    {
        public void howl()
        {
            string aa = "喵喵";
        }
    }

    public class test1
    {
        public static void UseIHowl()
        {
            IHowl Animal = new Cat();//把Cat的对象扔给IHowl接口，通过接口调用Cat类的对象
            Animal.howl();//执行了Cat类的实例对象中的howl()方法
        }
    }
    //接口可以根据赋值给它的对象的不同，而自行决定去调用不同的方法。如果在增加一个动物类，也只需要在声明接口变量Animal时，new 关键字后面的类型改变了而已，后续的代码不需要动。
    //这样，程序增加了可扩展性(多态)


    /**
            到这里接口的基本功能差不多讲完了。

            按照惯例，总结一下：

            1.定义接口的关键字是Interface。

            2.接口定义出来，是需要类去实现它的。无法直接New出一个接口。

            3.接口可以根据赋值的对象的类型不同，自动调用不同的方法。

            4.接口中定义的函数，前面不能加任何修饰词。
    **/

}
